import { ref, onMounted, onUnmounted, unref } from "vue";

export function useFullPage(options: { excludeFixedElements?: string[] } = {}) {
  const pageRef = ref<HTMLElement | null>(null);
  const { excludeFixedElements = [] } = options;

  const defaultFixedSelectors = [".custom-nav", ".van-nav-bar"];
  let cachedFixedHeight = 0;
  let resizeObserver: ResizeObserver | null = null;
  let mutationObserver: MutationObserver | null = null;

  function getDomElement(refEl: any): HTMLElement | null {
    const el = unref(refEl);
    if (el instanceof HTMLElement) return el;
    if (el?.el instanceof HTMLElement) return el.el;
    if (el?.$el instanceof HTMLElement) return el.$el;
    return null;
  }

  function calculateFixedElementsHeight() {
    const allSelectors = [...defaultFixedSelectors, ...excludeFixedElements].join(", ");
    if (!allSelectors.trim()) {
      cachedFixedHeight = 0;
      return;
    }

    let totalHeight = 0;
    document.querySelectorAll(allSelectors).forEach((el) => {
      const style = window.getComputedStyle(el);
      if (style.position === "fixed") {
        totalHeight += el.getBoundingClientRect().height;
      }
    });

    cachedFixedHeight = totalHeight;
  }

  function setFullSize() {
    requestAnimationFrame(() => {
      const dom = getDomElement(pageRef.value);
      if (!dom) return;

      const viewportHeight = window.innerHeight;
      const availableHeight = viewportHeight - cachedFixedHeight;

      dom.style.minHeight = `${availableHeight}px`;
      dom.style.height = dom.scrollHeight < availableHeight ? `${availableHeight}px` : "auto";
    });
  }

  function refreshSize() {
    calculateFixedElementsHeight();
    setFullSize();
  }

  /** 等待固定元素出现，并多次刷新保证稳定 */
  function waitForFixedElementsThenInit() {
    const allSelectors = [...defaultFixedSelectors, ...excludeFixedElements].join(", ");
    if (!allSelectors.trim()) {
      refreshSize();
      return;
    }

    mutationObserver = new MutationObserver(() => {
      const fixedEls = document.querySelectorAll(allSelectors);
      if (fixedEls.length > 0) {
        let count = 0;
        const interval = setInterval(() => {
          refreshSize();
          count++;
          if (count >= 5) {
            clearInterval(interval);
            mutationObserver?.disconnect();
          }
        }, 100);
      }
    });

    mutationObserver.observe(document.body, {
      childList: true,
      subtree: true,
    });
  }

  /** 动态监听新增固定元素，绑定 ResizeObserver */
  function observeFixedElements() {
    const allSelectors = [...defaultFixedSelectors, ...excludeFixedElements];
    resizeObserver = new ResizeObserver(refreshSize);

    const observeEls = () => {
      allSelectors.forEach((selector) => {
        document.querySelectorAll(selector).forEach((el) => {
          resizeObserver?.observe(el);
        });
      });
    };

    mutationObserver = new MutationObserver(() => {
      observeEls();
    });

    mutationObserver.observe(document.body, {
      childList: true,
      subtree: true,
    });

    observeEls();
  }

  onMounted(() => {
    waitForFixedElementsThenInit();
    observeFixedElements();

    // 安卓内嵌环境适当延迟首次刷新，保证首屏渲染完整
    setTimeout(() => {
      refreshSize();

      // 多次刷新，防止软键盘弹起影响视口高度导致初始计算不准
      let times = 0;
      const timer = setInterval(() => {
        refreshSize();
        times++;
        if (times >= 5) clearInterval(timer);
      }, 200);
    }, 300);

    window.addEventListener("resize", refreshSize);
  });

  onUnmounted(() => {
    window.removeEventListener("resize", refreshSize);
    resizeObserver?.disconnect();
    mutationObserver?.disconnect();
  });

  return { pageRef, refreshSize };
}
